#pragma once
#include "field.hpp"
#include "detail.hpp"
#include "abstruct.hpp"
#include <vector>

namespace bitRPC
{
    using Address = std::pair<std::string, int>;
    class JsonMessage : public BaseMessage
    {
    public:
        using ptr = std::shared_ptr<JsonMessage>;
        virtual std::string serialize() override
        {
            std::string body;
            bool ret = JSON::serialize(_body, body);
            if (ret == false)
            {
                return std::string();
            }
            return body;
        }
        virtual bool unserialize(const std::string &data) override // 针对接收到的数据进行一个解析
        {
            return JSON::unserialize(data, _body);
        }
        // 每个消息的检测规则是不同
    protected:
        Json::Value _body; // 正文相关信息
    };

    class JsonRequest : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonRequest>;
    };

    class JsonResponse : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonResponse>;
        virtual bool check() override
        {
            // 在响应中只有响应码
            //  判断响应码状态字段是否存在,类型是否正确
            if (_body[KEY_RCODE].isNull() == true)
            {
                ELOG("响应状态码不存在");
                return false;
            }
            if (_body[KEY_RCODE].isIntegral() == false)
            {
                ELOG("响应状态码类型错误");
                return false;
            }
            return true;
        }
        virtual Rcode rcode()
        {
            return (Rcode)_body[KEY_RCODE].asInt();
        }
        virtual void setRCode(Rcode rcode)
        {
            _body[KEY_RCODE] = (int)rcode;
        }
    };

    class RpcRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<RpcRequest>;
        virtual bool check() override
        {
            // 在RPC方法请求中的请求方法和字段是否存在或错误
            if (_body[KEY_METHOD].isNull() == true || _body[KEY_METHOD].isString() == false)
            {
                ELOG("请求方法不存在或类型错误");
                return false;
            }
            if (_body[KEY_PARAMATERS].isNull() == true || _body[KEY_PARAMATERS].isObject() == false)
            {
                ELOG("请求的参数不存在或类型错误");
                return false;
            }
            return true;
        }
        void setMethod(const std::string &method_name)
        {
            _body[KEY_METHOD] = method_name;
        }
        std::string getMethod()
        {
            return _body[KEY_METHOD].asString();
        }
        Json::Value param()
        {
            return _body[KEY_PARAMATERS];
        }
        void setParam(const Json::Value &param)
        {
            _body[KEY_PARAMATERS] = param;
        }
    };

    class TopicRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<TopicRequest>;
        virtual bool check() override
        {
            if (_body[KEY_TOPIC_KEY].isNull() == true || _body[KEY_TOPIC_KEY].isString() == false)
            {
                ELOG("主题请求中没有主题类型或者主题类型错误");
                return false;
            }
            if (_body[KEY_OPTYPE].isNull() == true || _body[KEY_OPTYPE].isIntegral() == false)
            {
                ELOG("主题操作不存在或者主题操作类型错误");
                return false;
            }
            if (_body[KEY_OPTYPE] == (int)TopicOptype::TOPIC_PUBLISH && (_body[KEY_TOPIC_MSG].isNull() == true || _body[KEY_TOPIC_MSG].isString() == false))
            {
                ELOG("主题发布中消息字段不存在或者消息字段类型错误");
                return false;
            }
            return true;
        }
        void setTopicKey(std::string key)
        {
            _body[KEY_TOPIC_KEY] = key;
        }
        std::string topicKey()
        {
            return _body[KEY_TOPIC_KEY].asString();
        }
        TopicOptype optype()
        {
            return (TopicOptype)_body[KEY_OPTYPE].asInt();
        }
        void setOptype(TopicOptype topicOptype_name)
        {
            _body[KEY_OPTYPE] = (int)topicOptype_name;
        }
        std::string topicMsg()
        {
            return _body[KEY_TOPIC_MSG].asString();
        }
        void setTopicMsg(const std::string &msg)
        {
            _body[KEY_TOPIC_MSG] = msg;
        }
    };
    class ServiceReqest : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<ServiceReqest>;
        virtual bool check()
        {
            if (_body[KEY_METHOD].isNull() == true ||
                _body[KEY_METHOD].isString() == false)
            {
                ELOG("服务请求中没有方法名称或方法名称类型错误！");
                return false;
            }
            if (_body[KEY_OPTYPE].isNull() == true ||
                _body[KEY_OPTYPE].isIntegral() == false)
            {
                ELOG("服务请求中没有操作类型或操作类型的类型错误！");
                return false;
            }
            if (_body[KEY_OPTYPE].asInt() != (int)(ServiceOptype::SERVICE_DISCOVERY) &&
                (_body[KEY_HOST].isNull() == true ||
                 _body[KEY_HOST].isObject() == false ||
                 _body[KEY_HOST][KEY_HOST_IP].isNull() == true ||
                 _body[KEY_HOST][KEY_HOST_IP].isString() == false ||
                 _body[KEY_HOST][KEY_HOST_PORT].isNull() == true ||
                 _body[KEY_HOST][KEY_HOST_PORT].isIntegral() == false))
            {
                ELOG("服务请求中主机地址信息错误！");
                return false;
            }
            return true;
        }
        std::string method()
        {
            return _body[KEY_METHOD].asString();
        }
        void setMethod(const std::string &name)
        {
            _body[KEY_METHOD] = name;
        }
        ServiceOptype optype()
        {
            return (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }
        void setOptype(ServiceOptype optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }
        Address host()
        {
            Address addr;
            addr.first = _body[KEY_HOST][KEY_HOST_IP].asString();
            addr.second = _body[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }
        void setHost(const Address &host)
        {
            Json::Value val;
            val[KEY_HOST_IP] = host.first;
            val[KEY_HOST_PORT] = host.second;
            _body[KEY_HOST] = val;
        }
    };
    class RpcResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<RpcResponse>;
        virtual bool check() override
        {
            // 在响应中只有响应码
            //  判断响应码状态字段是否存在,类型是否正确
            if (_body[KEY_RCODE].isNull() == true)
            {
                ELOG("响应状态码不存在");
                return false;
            }
            if (_body[KEY_RCODE].isIntegral() == false)
            {
                ELOG("响应状态码类型错误");
                return false;
            }
            if (_body[KEY_RESULT].isNull() == true)
            {
                ELOG("输出的结果不存在或者结果类型错误");
            }
            return true;
        }

        Json::Value result()
        {
            return _body[KEY_RESULT];
        }
        void setResult(const Json::Value &result)
        {
            _body[KEY_RESULT] = result;
        }
    };

    class TopicResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<TopicResponse>;
    };

    class ServiceResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<ServiceResponse>;

        virtual bool check() override
        {
            // 在响应中只有响应码
            //  判断响应码状态字段是否存在,类型是否正确
            if (_body[KEY_RCODE].isNull() == true)
            {
                ELOG("响应状态码不存在");
                return false;
            }
            if (_body[KEY_RCODE].isIntegral() == false)
            {
                ELOG("响应状态码类型错误");
                return false;
            }
            if (_body[KEY_OPTYPE].isNull() == true ||
                _body[KEY_OPTYPE].isIntegral() == false)
            {
                ELOG("服务响应中没有操作类型或操作类型的类型错误！");
                return false;
            }
            if((_body[KEY_OPTYPE].asInt() == (int)(ServiceOptype::SERVICE_DISCOVERY) &&
                   (_body[KEY_METHOD].isNull() == true ||
                    _body[KEY_METHOD].isString() == false ||
                    _body[KEY_HOST].isNull() == true ||
                    _body[KEY_HOST].isArray() == false))) 
                {
                    ELOG("服务发现响应中响应信息字段错误！");
                    return false;
                }
            return true;
        }

        ServiceOptype optype()
        {
            return (ServiceOptype)_body[KEY_OPTYPE].isInt();
        }
        void setOptype(ServiceOptype optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }
        std::vector<Address> hosts()
        {
            std::vector<Address> host;
            int n = _body[KEY_HOST].size();
            for (int i = 0; i < n; i++)
            {
                Address addr;
                addr.first = _body[KEY_HOST][i][KEY_HOST_IP].asString();
                addr.second = _body[KEY_HOST][i][KEY_HOST_PORT].asInt();
                host.push_back(addr);
            }
            return host;
        }
        void setHost(std::vector<Address> addrs)
        {
            for(auto &addr : addrs)
            {
                Json::Value val;
                val[KEY_HOST_IP] = addr.first;
                val[KEY_HOST_PORT] = addr.second;
                _body[KEY_HOST].append(val);
            }
        }
    };
    //实现一个消息对象的生产工厂
    class MessageFactory{
        public:
        //把类型给我们提供，就可以生产相应的消息对象
            static BaseMessage::ptr create(MType mtype)
            {
                switch(mtype)
                {
                    case MType::REQ_RPC:return std::make_shared<RpcRequest>();
                    case MType::REQ_SERVICE:return std::make_shared<ServiceReqest>();
                    case MType::REQ_TOPIC:return std::make_shared<TopicRequest>();
                    case MType::RES_RPC:return std::make_shared<RpcResponse>();
                    case MType::RES_SERVICE:return std::make_shared<ServiceResponse>();
                    case MType::RES_TOPIC:return std::make_shared<TopicResponse>();
                }
                return BaseMessage::ptr();
            }
            template<typename T,typename ...Args>
            static std::shared_ptr<T> create(Args&& ...args)
            {
                return std::make_shared<T>(std::forward(args)...);
            }

    };
}